package com.perfect.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.perfect.feign.GoodsFeignService;
import com.perfect.model.Order;
import com.perfect.service.OrderService;
import com.perfect.utils.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Random;
import java.util.UUID;
import java.util.stream.DoubleStream;

@RestController
@RequestMapping(value = "/order-test")
@RefreshScope
@Slf4j
public class TestController {

    @Autowired
    private ConfigurableApplicationContext applicationContext;

    @Value("${yunCloud.live.callBackUrl}")
    private String callBackUrl;

    @Autowired
    private OrderService orderService;

    @Autowired
    private GoodsFeignService goodsFeignService;

    @RequestMapping(value = "/nacos/config/test")
    public String configTest() {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String aa = environment.getProperty("aa");
        String out = String.format("读取nacos 配置 aa：%s,callBackUrl=%s", aa, callBackUrl);
        log.info(out);
        return out;
    }

    /**
     * SentinelResource
     * value： 受保护的资源名称
     * blockHandler: 被限流时触发的处理程序
     * fallback：降级方法
     * @return
     */
    @SentinelResource(value = "/sentinel/test",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/sentinel/test")
    public String sentinelTest(@RequestParam(required = false) String id) throws FlowException, InterruptedException {

        log.info("开始扣减商品数量...."+id);
        goodsFeignService.configTest();
        log.info("完成扣减商品数量...."+id);
        return "sentinel 测试方法："+id;
    }

    @SentinelResource(value = "/order/test1",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test1")
    public String orderTestOne(@RequestParam(required = false) String id)  {

        log.info("order test 1...."+id);
        goodsFeignService.configTest();
        log.info("order test 1...."+id);
        return "order test 1 测试方法："+id;
    }

    @SentinelResource(value = "/order/test2",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test2")
    public String orderTestTwo(@RequestParam(required = false) String id) throws InterruptedException {

        log.info("order test 2...."+id);
        goodsFeignService.configTest();
        Thread.sleep(1000);
        log.info("order test 2...."+id);
        return "order test 2 测试方法："+id;
    }

    @SentinelResource(value = "/order/test3",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test3")
    public String orderTestThree(@RequestParam(required = false) Integer id) throws InterruptedException {

        log.info("order test 3...."+id);
        if(id %2 ==0){
            throw new RuntimeException("异常了id，id=："+id);
        }
        log.info("order test 3...."+id);
        return "order test 3 测试方法："+id;
    }

    @SentinelResource(value = "/order/test4",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test4")
    public String orderTestFour(@RequestParam(required = false) Integer id) throws InterruptedException {

        log.info("order test 4...."+id);
        if(id %2 ==0){
            throw new RuntimeException("异常了id，id=："+id);
        }
        log.info("order test 4...."+id);
        return "order test 4 测试方法："+id;
    }

    @SentinelResource(value = "/order/test5",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test5")
    public String orderTestFive(@RequestParam(required = false) Integer id) throws InterruptedException {

        log.info("order test 5...."+id);
        String s = goodsFeignService.configTest();
        log.info(s);
        log.info("order test 5...."+id);
        return "order test 5 测试方法："+id;
    }

    @SentinelResource(value = "/order/test6",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test6")
    public String orderTestSix(@RequestParam(required = false) Integer id) throws InterruptedException {

        log.info("order test 6...."+id);
        log.info("order test 6...."+id);
        return "order test 6 测试方法："+id;
    }


    /**
     * 授权规则应用
     * @param id
     * @return
     * @throws InterruptedException
     */
    @SentinelResource(value = "/order/test7",
            blockHandler = "blockHandler",blockHandlerClass = ExceptionUtils.class,
            fallback = "fallback", fallbackClass = ExceptionUtils.class)
    @RequestMapping(value = "/order/test7")
    public String orderTestSeven(@RequestParam(required = false) String id) throws InterruptedException {

        System.out.println("order test 7...."+id);
//        String s = goodsFeignService.configTest();
//        System.out.println(s);
        System.out.println("order test 7...."+id);
        return "order test 7 测试方法："+id;
    }


    /**
     * seata 事务测试
     * @param id
     * @return
     */
    @RequestMapping(value = "/order/generator")
    public String orderGenerator(@RequestParam(required = false) String id)  {


        Order order = new Order();
        order.setCreateTime(new Date());
        Integer total = new Random().nextInt(4);
        order.setTotal(new BigDecimal(total.toString()));
        order.setOrderSn(UUID.randomUUID().toString());
        orderService.generatorOrder(order);
        return "orderGenerator 事务测试："+id;
    }


}
